//
// Created by admin on 2023-6-21.
//

#ifndef CPP20_RECIPES_INIT_MEMBER_H
#define CPP20_RECIPES_INIT_MEMBER_H

struct S {
    const int y = 42;
};
struct S1 {
    int x = 42; // default member initializer
};
struct S2 {
    int x;
    S2() : x {42} {} // ctor member initializer list
};

struct S3 {
    int x;
    S3() {
        x = 42; // ctor body
    }
};

// https://dfrib.github.io/the-fickle-aggregate/
struct A {
    int x;
    int y;
    int z;
    A() { x = 42; y=42 ;z=42 ;}
    A(int x, int y = 0 ,int z = 0) = delete;
    A(int x) {
        x = x;
    }
    /// out put x =  N +1
    A SetX(int x) {
        (*this).x = x + 1;
        return *this;
    }
    /// out put *this.y = 42
    A SetY(int y) {
        y = y + 1;
        return *this;
    }
    /// out put z = y + 1
    A SetZ(int y) {
        z = y + 1;
        return *this;
    }


};

namespace detail {
template <int N>
struct NumberImpl final {
    const int value {N};
    // Factory method for NumberImpl<N> wrapping non-type
    // template parameter 'N' as data member 'value'.
    static const NumberImpl& get() {
        static constexpr NumberImpl number {};
        return number;
    }

private:
    NumberImpl() = default;
    /// 构造造函数
    NumberImpl(int) = delete;
    /// 拷贝构造函数
    NumberImpl(const NumberImpl&) = delete;
    /// 移动构造函数
    NumberImpl(NumberImpl&&) = delete;
    /// 赋值构造函数
    NumberImpl& operator=(const NumberImpl&) = delete;
    /// 赋值移动构造函数
    NumberImpl& operator=(NumberImpl&&) = delete;
};
} // namespace detail

// Intended public API.
template<int N>
using Number = detail::NumberImpl<N>;

template<int N>
bool wrappedValueIsN(const Number<N>& num) {
    // Always 'true', by design of the 'NumberImpl' class?
    return N == num.value;
}

#include <string>
#include <iostream>

/// C++存在3种方式初始化成员，分别为：
///- ctor member initializer list
///- ctor body
///- default member initializer (in-class initializer)

/// default member initializer
/// 如果 default member initializer 和 ctor member initializer list 同时出现，
/// 那么前者会被忽略，所以也不会导致重复初始化。
struct S4 {
    int x = 1;
    double y = 2.0;
    std::string s{"text1"};
    /// alias of std::string
    using string = std::string;

    S4() {}
    S4(int val): x(val) {}
    S4(double val): y(val){}
    S4(const string& val): s(val){}
    S4(int x, double y, const string &s): x{x},y{y},s{s}{}
};

std::ostream &operator <<(std::ostream& os, const S4& rhs);
#endif //CPP20_RECIPES_INIT_MEMBER_H
